package jmine.tec.environment.utils;

import java.io.File;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * @author Rafael Volpato (May 11, 2007)
 * @author galmeida (Sep 24, 2008)
 */
public class SpringConfigFactory {
    private static final Logger LOG = Logger.getLogger(SpringConfigFactory.class);

    /**
     * Propriedade onde é guardado o tipo de banco de dados a ser utilizado.
     */
    public static final String TEST_DATABASE_PROPERTY_NAME = "test.database";

    public static final String TEST_DATABASE_CONFIGURATION_FILE = "test.database.configuration.filename";

    /**
     * Nome do bean do datasource sem dados carregados.
     */
    public static final String DATA_SOURCE_BEAN_NAME = "baseTestDataSource";

    /**
     * Nome do bean das properties do hibernate.
     */
    public static final String HIBERNATE_PROPERTIES_BEAN_NAME = "hibernateProperties";

    /**
     * Nome do bean com o TestDBServer.
     */
    public static final String DB_SERVER_BEAN_NAME = "testDBServer";

    /**
     * Valor padrão para o banco de dados.
     */
    private static final String DATABASE_PROPERTY_DEFAULT = "h2-sequence";

    /**
     * Subdiretório de $HOME onde serão procuradas as configs.
     */
    private static final String HOME_CONFIG_DIR = ".jmine/tec.test/";

    private static final String DATASOURCE_CONFIG_DIR = "datasource/";

    private static final String HIBERNATE_CONFIG_DIR = "hibernate/";

    private String databaseType;

    private ApplicationContext applicationContext = null;

    /**
     * Construtor, identifica o banco de dados selecionado.
     */
    public SpringConfigFactory() {
        this(System.getProperty(TEST_DATABASE_PROPERTY_NAME, DATABASE_PROPERTY_DEFAULT));

    }

    /**
     * Construtor.
     * 
     * @param databaseType o tipo de base de dados.
     */
    public SpringConfigFactory(String databaseType) {
        this.databaseType = System.getProperty(TEST_DATABASE_PROPERTY_NAME, DATABASE_PROPERTY_DEFAULT);

    }

    /**
     * Devolve o {@link ApplicationContext} com as configurações básicas de hibernate e datasource.
     * 
     * @return o {@link ApplicationContext} com as configurações básicas de hibernate e datasource.
     */
    public ApplicationContext getApplicationContext() {
        if (this.applicationContext == null) {
            String datasourceConfig = this.getResourcePath(DATASOURCE_CONFIG_DIR + this.databaseType + ".xml");
            String hibernateConfig = this.getResourcePath(HIBERNATE_CONFIG_DIR + this.databaseType + ".xml");
            LOG.info("DataSource config: " + datasourceConfig);
            LOG.info(" Hibernate config: " + hibernateConfig);
            this.applicationContext = new FileSystemXmlApplicationContext(new String[]{ datasourceConfig, hibernateConfig });
        }
        return this.applicationContext;
    }

    /**
     * Devolve o bd selecionado.
     * 
     * @return o bd selecionado.
     */
    public String getDatabaseServerType() {
        return this.databaseType;
    }

    /**
     * Devolve o resource do $HOME ou do classpath se o do $HOME não exitir.
     * 
     * @param defaultPath path do resource
     * @return o resource do $HOME ou do classpath se o do $HOME não exitir.
     */
    private String getResourcePath(String defaultPath) {
        String homePath = System.getProperty("user.home") + "/" + HOME_CONFIG_DIR + defaultPath;

        if (new File(homePath).canRead()) {
            return "file:" + homePath;
        } else {
            return "classpath:" + defaultPath;
        }
    }
}
